/**
 * @author wangzhongjie
 * @desc 计算数值
 * @date 2019/3/18
 */
var Measure = function () {

    // 获取的宽高
    this.dynamicX = null;
    this.dynamicY = null;

    // 缩放比例
    this.scalingX = null;
    this.scalingY = null;

    // 当前处理的顶点数组
    this.vertexs = [];

    // 当前人员的三围测量值
    this.personXY = null;
    // 原始三围正侧宽平均值
    this.origineXY = null;

    // 原始肩宽平均值
    this.origineShoulder = null;

    // 缩放比例
    this.scalingB = null;
    this.scalingW = null;
    this.scalingH = null;

    /**
     * data: 待处理的50条数据
     * gender: 性别 1男 0女
     * callback: 参数 三围和正侧宽的值
     */
    this.disposeData = function (data, gender, callback) {

        if (!data || data.length === 0) return false;

        var array = divideArrays(data);

        // 判断是否是session本地存储
        isSession(function (v) {

            var personalData = null;
            var result = null;

            // 处理男三围数据
            if (gender == 1) {

                personalData = dispatchData({

                    chestArray: array.chestArray,
                    waistlineArray: array.waistlineArray,
                    hiplineArray: array.hiplineArray,
                    ribArray: array.ribArray// 新增肋间数据

                }, v.man);

                personalData = processingNum(personalData, gender, array);

                // 暂时使用不处理的肩宽，不做处理
                // array.shoulder = array.shoulder * (1 - 0.260351395);

                result = {

                    shoulder: parseInt(array.shoulder * (1 + 0.24931694)),
                    bust: parseInt(MathTool.multiply(personalData.bust, (1 - 0.260889251))),// 胸围
                    waistline: parseInt(MathTool.multiply(personalData.waistline, (1 - 0.152507159))),// 腰围
                    hipline: parseInt(MathTool.multiply(personalData.hipline, (1 - 0.002616711))),// 臂围
                    presonXY: scope.personXY //三围正侧宽
                };

                callback(result);

            }

            // 处理女三围数据
            if (gender == 0) {

                personalData = dispatchData({

                    chestArray: array.chestArray,
                    waistlineArray: array.waistlineArray,
                    hiplineArray: array.hiplineArray,
                    ribArray: array.ribArray// 新增肋间数据

                }, v.woman);

                personalData = processingNum(personalData, gender, array);

                // 暂时使用不处理的肩宽，不做处理
                // array.shoulder = array.shoulder * (1 - 0.316697474);

                result = {

                    shoulder: parseInt(array.shoulder),
                    bust: parseInt(MathTool.multiply(personalData.bust, (1 + 0.054408518))),// 胸围
                    waistline: parseInt(MathTool.multiply(personalData.waistline, (1 - 0.023503965))),// 腰围
                    hipline: parseInt(MathTool.multiply(personalData.hipline, (1 + 0.017662885))),// 臂围
                    presonXY: scope.personXY// 三围正侧宽
                };

                callback(result);

            }

            sessionStorage.setItem('personCurrent', JSON.stringify(result));

        });

    };

    /**
     * bwh 为用户输入的数据
     * b: 胸围
     * w: 腰围
     * h: 臀围
     * 依据原始三围比例计算正侧宽
     * 计算依据是 缓存中的原始值
     * return：presonXY
     */
    this.getScallBwhXY = function (b, w, h) {

        var bv = new BWH(b);
        var wv = new BWH(w);
        var hv = new BWH(h);
        var bwh = [bv, wv, hv];

        // 验证数值是否符合规则
        var res = bwh.every(function (bwh) {

            return bwh.validate();

        });

        var pCurrent = JSON.parse(sessionStorage.getItem('personCurrent'));

        // 若不符合返回null
        if (!pCurrent || !res) {

            return null;

        }

        var sessionB = pCurrent.bust; // 胸围
        var sessionW = pCurrent.waistline;// 腰围
        var sessionH = pCurrent.hipline;// 臀围

        scope.scalingB = b / sessionB;
        scope.scalingW = w / sessionW;
        scope.scalingH = h / sessionH;

        var presonXY = pCurrent.presonXY;

        pCurrent.bust = b;
        pCurrent.waistline = w;
        pCurrent.hipline = h;

        var bw = presonXY.chestXY.width;
        var bh = presonXY.chestXY.height;

        var ww = presonXY.waistlineXY.width;
        var wh = presonXY.waistlineXY.height;

        var hw = presonXY.hiplineXY.width;
        var hh = presonXY.hiplineXY.height;

        // 依据缩放值计算宽高
        bw *= scope.scalingB;
        bh *= scope.scalingB;

        ww *= scope.scalingW;
        wh *= scope.scalingW;

        hw *= scope.scalingH;
        hh *= scope.scalingH;

        presonXY.chestXY.width = Number(bw.toFixed(2));
        presonXY.chestXY.height = Number(bh.toFixed(2));

        presonXY.waistlineXY.width = Number(ww.toFixed(2));
        presonXY.waistlineXY.height = Number(wh.toFixed(2));

        presonXY.hiplineXY.width = Number(hw.toFixed(2));
        presonXY.hiplineXY.height = Number(hh.toFixed(2));

        sessionStorage.setItem('personCurrent', JSON.stringify(pCurrent));

        return presonXY;

    };


    /**
     * b:胸围
     * W:腰围
     * h:臀围
     * gender:性别
     * 依据三围参数和顶点数据计算正宽值
     */
    this.disposeBwhXY = function (b, w, h, gender, callback) {

        isSession(function (v) {

            console.log('nimei');
            var manV = v.man;
            var womanV = v.woman;

            var bw = 0, bh = 0, ww = 0, wh = 0, hw = 0, hh = 0;
            var presonXY = null;

            // 男
            if (gender == 1) {

                // 默认使用第一条取线
                var mbV = manV.chest.vertices0;
                var mwV = manV.waistline.vertices0;
                var mhV = manV.hipline.vertices0;


                scope.scalingB = b / mbV.length;
                scope.scalingW = b / mwV.length;
                scope.scalingH = b / mhV.length;

                // 胸正侧宽
                bw = scope.scalingB * mbV.width;
                bh = scope.scalingB * mbV.height;

                // 腰正侧宽
                ww = scope.scalingW * mwV.width;
                wh = scope.scalingW * mwV.height;

                // 臀正侧宽
                hw = scope.scalingH * mhV.width;
                hh = scope.scalingH * mhV.height;

                // 优化插值
                // bw = bw * (1 - 0.058479532 - 0.050301373);
                // ww = ww * (1 - 0.127906977 - 0.052527365);
                // hw = hw * (1 - 0.022408964 - 0.030666541);

                // bh = bh * (1 - 0.004149378 - 0.148668352);
                // wh = wh * (1 - 0.089604265 - 0.078677298);
                // hh = hh * (1 + 0.059574468 + 0.107426115);

                presonXY = {
                    chestXY: {
                        width: Number(bw.toFixed(2)),
                        height: Number(bh.toFixed(2))
                    },
                    waistlineXY: {
                        width: Number(ww.toFixed(2)),
                        height: Number(wh.toFixed(2))
                    },
                    hiplineXY: {
                        width: Number(hw.toFixed(2)),
                        height: Number(hh.toFixed(2))
                    }

                };
                callback(presonXY);

            }

            // 女
            if (gender == 0) {

                // 默认使用第一条曲线
                var wbV = womanV.chest.vertices0;
                var wwV = womanV.waistline.vertices0;
                var whV = womanV.hipline.vertices0;


                scope.scalingB = b / wbV.length;
                scope.scalingW = b / wwV.length;
                scope.scalingH = b / whV.length;

                // 胸正侧宽
                bw = scope.scalingB * wbV.width;
                bh = scope.scalingB * wbV.height;

                // 腰正侧宽
                ww = scope.scalingW * wwV.width;
                wh = scope.scalingW * wwV.height;

                // 臀正侧宽
                hw = scope.scalingH * whV.width;
                hh = scope.scalingH * whV.height;

                // bw = bw * (1 - 0.115951113 - 0.132567313);
                // ww = ww * (1 - 0.09676343 - 0.129775144);
                // hw = hw * (1 + 0.017756733 - 0.075713525);
                //
                // bh = bh * (1 + 0.032989691 - 0.112953285);
                // wh = wh * (1 - 0.212169736 + 0.006985498);
                // hh = hh * (1 + 0.075926753 + 0.209727125);

                presonXY = {
                    chestXY: {
                        width: Number(bw.toFixed(2)),
                        height: Number(bh.toFixed(2))
                    },
                    waistlineXY: {
                        width: Number(ww.toFixed(2)),
                        height: Number(wh.toFixed(2))
                    },
                    hiplineXY: {
                        width: Number(hw.toFixed(2)),
                        height: Number(hh.toFixed(2))
                    }

                };

                callback(presonXY);

            }

        })

    };


    /**
     * 内部构件
     */
    var scope = this;

    // 顶点json数据
    var url = './js/vertex.json';

    // JSON文件加载器
    var fileLoader = new THREE.FileLoader();

    /**
     * 顶点文件加载
     */
    function verticeLoaded(url, callback) {

        fileLoader.load(url, function (data) {

            sessionStorage.setItem('vertices-json', data);

            callback(JSON.parse(data));

        });

    }

    /**
     * 是否有session缓存
     */
    function isSession(callback) {

        var v = sessionStorage.getItem('vertices190405');

        if (v) {

            callback(JSON.parse(v));

        } else {

            verticeLoaded(url, function (v) {

                callback(v);

            })

        }

    }

    /**
     * 处理腰围
     */
    function disposeWaistline(data, xy) {

        return dispose(data.width, data.height, data.vertices, xy);

    }

    /**
     * 处理胸围
     */
    function disposeChest(data, xy) {

        return dispose(data.width, data.height, data.vertices, xy);

    }

    /**
     * 处理臂围
     */
    function disposeHipline(data, xy) {

        return dispose(data.width, data.height, data.vertices, xy);

    }

    /**
     * 对三围数据进行分组
     */
    function divideArrays(array) {

        if (array.length === 0) return false;

        var chestArray = []; // 胸围数据
        var waistlineArray = []; //腰围数据
        var hiplineArray = [];//臂围数据
        var ribArray = [];// 新增胸围到腰围之间的取值

        for (var i = 0; i < array.length; i++) {

            // 胸取线 12 - 14条 正宽计算 FaceRightwidth * 2
            if (i >= 11 && i <= 13) {

                chestArray.push(array[i]);

            }

            // 肋取线 18 - 21条
            if (i >= 17 && i <= 20) {

                ribArray.push(array[i]);

            }

            // 腰取线 22 - 24 条
            if (i >= 21 && i <= 23) {

                waistlineArray.push(array[i]);

            }

            // 臀取线 27 - 31条
            if (i >= 26 && i <= 30) {

                hiplineArray.push(array[i]);

            }

        }

        // 计算肩宽 取值 第三条 -- 第四条
        var shoulderArray = [array[2], array[3], array[4], array[5]];

        var leftWidth = 0;

        shoulderArray.forEach(function (value) {
            leftWidth += value.FaceLeftwidth;
        });

        var shoulder = (leftWidth * 2 / shoulderArray.length) * (1 - 0.24931694);

        // 原始肩宽值
        scope.origineShoulder = shoulder;

        return {

            shoulder: shoulder, // 肩宽是第三条数据
            chestArray: chestArray,
            waistlineArray: waistlineArray,
            hiplineArray: hiplineArray,
            ribArray: ribArray// 新增肋间数据

        }

    }

    /**
     * 分派顶点分组选取数据流程
     */
    function dispatchData(arrays, personal) {

        /**
         * 处理数据
         */
        var chestXY = disposeArray(arrays.chestArray, 'chest');
        var waistlineXY = disposeArray(arrays.waistlineArray);
        var hiplineXY = disposeArray(arrays.hiplineArray);

        // 新增肋间数据
        var ribXY = disposeArray(arrays.ribArray);

        // 原始测量值
        scope.origineXY = {

            chestXY: chestXY,
            waistlineXY: waistlineXY,
            hiplineXY: hiplineXY,
            ribXY: ribXY,// 新增肋数据
            shoulder: scope.origineShoulder

        };

        scope.origineXY = JSON.stringify(scope.origineXY);

        // 处理女正侧宽
        if (personal.type == 'woman') {

            // 胸正
            chestXY.width = chestXY.width * (1 - 0.350982636);
            // 腰
            waistlineXY.width = waistlineXY.width * (1 - 0.279836305);
            // 臀
            hiplineXY.width = hiplineXY.width * (1 - 0.059870452);

            // 肋
            ribXY.width = ribXY.width * (1 - 0.230229798);

            // 胸侧
            chestXY.height = chestXY.height * (1 - 0.216018009);
            // 腰
            waistlineXY.height = waistlineXY.height * (1 - 0.308627451);
            // 臀
            hiplineXY.height = hiplineXY.height * (1 + 0.044306859);

            // 肋
            ribXY.height = ribXY.height * (1 - 0.160112867);

        }

        // 处理男正侧宽
        if (personal.type == 'man') {

            // 胸正
            chestXY.width = chestXY.width * (1 - 0.03841716);
            // 腰
            waistlineXY.width = waistlineXY.width * (1 - 0.171790405);
            // 臀
            hiplineXY.width = hiplineXY.width * (1 - 0.036676477);

            // 肋
            ribXY.width = ribXY.width * (1 - 0.082294681);

            // 胸侧
            chestXY.height = chestXY.height * (1 + 0.109026255);
            // 腰
            waistlineXY.height = waistlineXY.height * (1 + 0.155770024);
            // 臀
            hiplineXY.height = hiplineXY.height * (1 + 0.061226421);

            // 肋
            ribXY.height = ribXY.height * (1 + 0.108674233);

        }

        var bustV = classify(chestXY, personal.chest);
        var waistlineV = classify(waistlineXY, personal.waistline);
        var hiplineV = classify(hiplineXY, personal.hipline);

        // 保留两位小数
        chestXY.width = Number(chestXY.width.toFixed(2));
        chestXY.height = Number(chestXY.height.toFixed(2));

        waistlineXY.width = Number(waistlineXY.width.toFixed(2));
        waistlineXY.height = Number(waistlineXY.height.toFixed(2));

        hiplineXY.width = Number(hiplineXY.width.toFixed(2));
        hiplineXY.height = Number(hiplineXY.height.toFixed(2));

        ribXY.width = Number(ribXY.width.toFixed(2));
        ribXY.height = Number(ribXY.height.toFixed(2));

        // 保存计算过后的 三围正侧宽的值
        scope.personXY = {

            chestXY: chestXY,
            waistlineXY: waistlineXY,
            hiplineXY: hiplineXY,
            ribXY: ribXY,// 新增肋数据
            origineXY: scope.origineXY

        };

        return {

            bust: disposeChest(bustV, chestXY),
            waistline: disposeWaistline(waistlineV, waistlineXY),
            hipline: disposeHipline(hiplineV, hiplineXY)

        }
    }

    /**
     * 处理区间范围
     */
    function classify(dimensional, personal) {

        // 暂时不分男女处理器区间
        // 小于255
        if (dimensional.height <= 255) {

            // 女士胸围曲线已更换未原来的那条
            return personal.vertices0;

            // 255 - 275
        } else if (dimensional.height <= 275) {

            return personal.vertices1;

            // 275以上
        } else {

            return personal.vertices2;

        }

    }

    /**
     * 处理可用数据，返回宽高平均值
     */
    function disposeArray(array, type) {

        var width = 0;
        var height = 0;
        var indexArray = 0;

        if (type == 'chest') {
            // 循环处理非0数据，并计算平均值
            array.forEach(function (value) {

                if (Math.abs(value.FaceRightwidth) == 0
                    || Math.abs(value.Leftwidth) == 0
                    || Math.abs(value.rightwidth) == 0) {

                    return false;

                }

                // 可用数据个数
                indexArray++;

                width += value.FaceRightwidth * 2;
                height += value.Leftwidth + value.rightwidth;

            });

        } else {
            // 循环处理非0数据，并计算平均值
            array.forEach(function (value) {

                if (Math.abs(value.FaceLeftwidth) == 0
                    || Math.abs(value.FaceRightwidth) == 0
                    || Math.abs(value.Leftwidth) == 0
                    || Math.abs(value.rightwidth) == 0) {

                    return false;

                }

                // 可用数据个数
                indexArray++;

                width += value.FaceLeftwidth + value.FaceRightwidth;
                height += value.Leftwidth + value.rightwidth;

            });

        }

        // 返回一组数的平均宽高值
        return {

            width: MathTool.divide(width, indexArray),
            height: MathTool.divide(height, indexArray)

        };

    }

    /**
     * 非数值处理规则
     * 胸围是 NaN AVG(腰围+臀围)
     * 腰围是 NaN AVG(臀围+胸围)
     * 臀围是 NaN AVG(胸围+腰围)
     * personalData: 三围数据
     */
    function processingNum(personalData, gender, array) {

        var shoulder = array.shoulder;
        var bust = personalData.bust;
        var hipline = personalData.hipline;
        var waistline = personalData.waistline;

        if (shoulder == 0) return;

        // 判断腰围是否为NaN
        if (isNaN(bust)) {

            // 若臀围和腰围有一个为NaN就return
            if (!isNaN(hipline) && !isNaN(waistline)) {

                bust = gender == '0' ? ((waistline + hipline) / 2) * 1.08 : ((waistline + hipline) / 2) * 1.02;

            }

        }

        if (isNaN(waistline)) {

            if (!isNaN(bust) && !isNaN(hipline)) {

                waistline = gender == '0' ? ((bust + hipline) / 2) * 1.22 : ((bust + hipline) / 2) * 1.12;

            }

        }

        if (isNaN(hipline)) {

            if (!isNaN(bust) && !isNaN(waistline)) {

                hipline = ((bust + waistline) / 2) * 0.89;

            }

        }

        // 胸围和腰围是NaN
        if (isNaN(bust) && isNaN(waistline)) {

            bust = gender == '0' ? hipline * 0.95 : hipline * 1.02;
            waistline = gender == '0' ? hipline * 0.89 : hipline * 0.96;

        }

        // 腰围和臀围是NaN
        if (isNaN(bust) && isNaN(hipline)) {

            bust = gender == '0' ? waistline * 1.12 : waistline * 1.04;
            hipline = gender == '0' ? waistline * 1.22 : waistline * 0.98;

        }

        // 臀围和腰围是NaN
        if (isNaN(waistline) && isNaN(hipline)) {

            waistline = gender == '0' ? bust * 0.89 : bust * 0.98;
            hipline = gender == '0' ? bust * 1.04 : bust * 0.99;

        }

        // 若胸腰臀都不是数字 -- 则通过肩宽处理
        if (isNaN(bust) && isNaN(hipline) && isNaN(waistline)) {

            for (var key in personalData) {

                if (key == 'bust') {

                    bust = gender == '0' ? shoulder * 2.42 : shoulder * 2.32;

                } else if (key == 'hipline') {

                    hipline = gender == '0' ? shoulder * 2.1 : shoulder * 2.2;

                } else if (key == 'waistline') {

                    hipline = gender == '0' ? shoulder * 2.6 : shoulder * 2.4;

                }

            }

        }

        // 正侧宽为NaN 则赋值为肩宽的值
        for (var key1 in scope.personXY) {

            var obj = scope.personXY[key1];

            for (var key2 in obj) {

                if (isNaN(obj[key2])) {

                    obj[key2] = Number((array.shoulder * 0.82).toFixed(2));

                }

            }

        }

        return {bust: bust, waistline: waistline, hipline: hipline};

    }

    /**
     * 处理顶点数据
     */
    function dispose(originalX, originalY, vertices, xy) {

        for (var i = 0; i < vertices.length; i += 3) {

            var vector3 = new THREE.Vector3(
                vertices[i],
                vertices[i + 1],
                vertices[i + 2]
            );

            scope.vertexs.push(vector3);

        }

        // 求出缩放比例
        scope.scalingX = MathTool.divide(xy.width, originalX);
        scope.scalingY = MathTool.divide(xy.height, originalY);

        // 开始缩放
        scope.vertexs.forEach(function (value) {

            value.x = MathTool.multiply(value.x, scope.scalingX);
            value.z = MathTool.multiply(value.z, scope.scalingY);

        });

        // 测量线段长度
        var length = 0;

        scope.vertexs.forEach(function (value, index) {

            if (index + 1 === scope.vertexs.length) {

                return false;

            }

            length = MathTool.add(length, value.distanceTo(scope.vertexs[index + 1]));

        });

        // 清空顶点数组
        scope.vertexs = [];

        // 返回int值
        return parseInt(length);

    }

};

/**
 * @author wangzhongjie
 * @desc 三围验证方法
 * @date 2019/3/29
 */
function BWH(value) {

    this.value = value;
    this.minVal = 0;
    this.maxVal = 2000;

}

BWH.prototype.validate = function () {

    if (isNaN(Number(this.value))) {

        return false;

    }

    return this.value > this.minVal
        && this.value < this.maxVal;

};

